package com.jwater.core.net.group.data;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jwater.launch.HomePath;

import jwater.org.apache.commons.io.FilenameUtils;
/**
 * @description:
 * @author: jnner
 * @createDate: 2021/2/5
 * @version: 1.0
 */
public class DurableDataManager {
	protected static Logger logger = LoggerFactory.getLogger(DurableDataManager.class);
	public static final String DURABLE_DATA_PATH = HomePath.getDurableDataPath();

	private Map<String, DurableData> datas = new ConcurrentHashMap<>(16);
	private Thread durableThread;
	private Set<String> excludes = new CopyOnWriteArraySet<String>();

	public void startDurableThread() {
		durableThread = new Thread(() -> store());
		durableThread.start();
	}

	public void closeDurableThread() {
		if (durableThread != null) {
			synchronized (this) {
				durableThread.interrupt();
			}
		}
	}

	public void set(String key, boolean isDurable) {
		if (isDurable) {
			excludes.remove(key);
		} else {
			excludes.add(key);
		}
	}

	/**
	 *
	 */
	public void store() {
		while (true) {
			try {
				synchronized (this) {
					this.wait(1000);
				}
			} catch (InterruptedException e) {
				break;
			}
			try {
				for (Entry<String, DurableData> en : datas.entrySet()) {
					String key = en.getKey();
					if (excludes.contains(key)) {
						continue;
					}
					DurableData durableData = en.getValue();
					if (durableData.getUpdate()) {
						durableData.setUpdate(false);
						durableData.store(DURABLE_DATA_PATH, key + ".data");
					}
				}
			} catch (Exception e) {
				logger.error(e.toString(), e);
			}
		}
	}

	public void load() {
		File dir = new File(DURABLE_DATA_PATH);
		if (dir.exists()) {
			File[] files = dir.listFiles();
			for (File file : files) {
				DurableData durableData = new DurableData();
				durableData.load(DURABLE_DATA_PATH, file.getName());
				datas.put(FilenameUtils.getBaseName(file.getName()), durableData);
			}
		}
	}

	public Map<String, DurableData> datas() {
		return datas;
	}

	public DurableData getData(String key) {
		return datas.get(key);
	}

	public DurableDataItem getItem(String key, String itemKey) {
		DurableData durableData = getData(key);
		if (durableData != null) {
			return durableData.getItem(itemKey);
		}
		return null;
	}

	public Map<String, DurableDataItem> getItemsByPrefix(String key, String prefix) {
		DurableData durableData = getData(key);
		if (durableData != null) {
			return durableData.getItemsByPrefix(key, prefix);
		}
		return new HashMap<String, DurableDataItem>();
	}

	public void setItem(String key, String itemKey, long version, String data) {
		DurableData durableData = getData(key);
		if (durableData == null) {
			durableData = new DurableData();
			datas.put(key, durableData);
		}
		durableData.setItem(itemKey, version, data);
	}

	public void removeItem(String key, String itemKey) {
		DurableData durableData = getData(key);
		if (durableData != null) {
			durableData.removeItem(itemKey);
		}
	}
}
